﻿using System.Collections;

namespace Bzstd.Utility.Assertion;

/// <summary>
/// 集合断言类
/// </summary>
public static partial class Assert
{
	/// <summary>
	/// 集合索引断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="index"></param>
	/// <param name="message"></param>
	/// <typeparam name="T"></typeparam>
	/// <returns></returns>
	public static int ValidIndex<T>(T enumerable, int index, string message) where T : IEnumerable
	{
		return (int) Range(0, enumerable?.Cast<object>().Count() ?? 0, index, message);
	}

	/// <summary>
	/// 集合非空断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <typeparam name="T"></typeparam>
	/// <returns></returns>
	public static T NotEmpty<T>(T enumerable, string message) where T : IEnumerable
	{
		IsTrue(enumerable?.Cast<object>().Any() == true, message);
		return enumerable;
	}

	/// <summary>
	/// 集合非空断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <typeparam name="T"></typeparam>
	/// <returns></returns>
	public static T NoNullElements<T>(T enumerable, string message) where T : IEnumerable
	{
		IsTrue(enumerable?.Cast<object>().All(e => e != null) == true, message);
		return enumerable;
	}

	/// <summary>
	/// 集合非空且无空元素断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <typeparam name="T"></typeparam>
	/// <returns></returns>
	public static T NotEmptyAndNoNullElements<T>(T enumerable, string message) where T : IEnumerable
	{
		NotEmpty(enumerable, message);
		NoNullElements(enumerable, message);
		return enumerable;
	}

	/// <summary>
	/// 集合无空元素断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <returns></returns>
	public static IEnumerable<string> NoEmptyElements(IEnumerable<string> enumerable, string message)
	{
		if (enumerable != null)
		{
			IsTrue(enumerable.All(s => !string.IsNullOrEmpty(s)), message);
		}

		return enumerable;
	}

	/// <summary>
	/// 集合非空且无空元素断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <returns></returns>
	public static IEnumerable<string> NotEmptyAndNoEmptyElements(IEnumerable<string> enumerable, string message)
	{
		NotEmpty(enumerable, message);
		NoEmptyElements(enumerable, message);
		return enumerable;
	}

	/// <summary>
	/// 集合无空元素断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <returns></returns>
	public static IEnumerable<string> NoBlankElements(IEnumerable<string> enumerable, string message)
	{
		if (enumerable != null)
		{
			IsTrue(enumerable.All(s => !string.IsNullOrWhiteSpace(s)), message);
		}

		return enumerable;
	}

	/// <summary>
	/// 集合非空且无空元素断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <returns></returns>
	public static IEnumerable<string> NotEmptyAndNoBlankElements(IEnumerable<string> enumerable, string message)
	{
		NotEmpty(enumerable, message);
		NoEmptyElements(enumerable, message);
		return enumerable;
	}

	/// <summary>
	/// 集合值唯一断言
	/// </summary>
	/// <param name="enumerable"></param>
	/// <param name="message"></param>
	/// <typeparam name="E"></typeparam>
	/// <returns></returns>
	public static E SingleElement<E>(IEnumerable<E> enumerable, string message)
	{
		NotEmpty(enumerable, message);
		return NotCatch<InvalidOperationException, E>(enumerable.Single, message);
	}

	/// <summary>
	/// 集合值唯一且非空断言
	/// </summary>
	/// <param name="iterable"></param>
	/// <param name="message"></param>
	/// <typeparam name="E"></typeparam>
	/// <returns></returns>
	public static E singleNotNullElement<E>(IEnumerable<E> iterable, string message)
	{
		return NotNull(SingleElement(iterable, message), message);
	}

	/// <summary>
	/// 集合值唯一且非空断言
	/// </summary>
	/// <param name="iterable"></param>
	/// <param name="message"></param>
	/// <typeparam name="E"></typeparam>
	/// <returns></returns>
	public static E singleNotEmptyElement<E>(IEnumerable<E> iterable, string message)
	{
		return NotNull(SingleElement(iterable, message), message);
	}

	/// <summary>
	/// 集合值唯一且非空断言
	/// </summary>
	/// <param name="iterable"></param>
	/// <param name="message"></param>
	/// <typeparam name="E"></typeparam>
	/// <returns></returns>
	public static E singleNotBlankElement<E>(IEnumerable<E> iterable, string message)
	{
		return NotNull(SingleElement(iterable, message), message);
	}
}
